package com.oneonefive.educationsystem.service.impl;

import cn.hutool.jwt.JWTUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.oneonefive.educationsystem.domain.Login;
import com.oneonefive.educationsystem.domain.User;
import com.oneonefive.educationsystem.dto.Result;
import com.oneonefive.educationsystem.dto.UserDTO;
import com.oneonefive.educationsystem.mapper.UserMapper;
import com.oneonefive.educationsystem.service.UserService;
import com.oneonefive.educationsystem.utils.Constant;
import com.oneonefive.educationsystem.utils.RedisUtil;
import com.oneonefive.educationsystem.utils.ReflectUtil;
import com.oneonefive.educationsystem.utils.StateChangeUtil;
import com.oneonefive.educationsystem.vo.UserVo;
import io.netty.util.internal.StringUtil;
import jakarta.annotation.Resource;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.util.*;


@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
        implements UserService {

    @Resource
    UserMapper userMapper;


    @Resource
    StringRedisTemplate stringRedisTemplate;

    @Resource
    RedisTemplate redisTemplate;

    @Resource
    AuthenticationManager authenticationManager;

    @Override
    public Result login(User user) {
        if (StringUtil.isNullOrEmpty(user.getAccount()) || StringUtil.isNullOrEmpty(user.getPassword())) {
            return Result.fail("用户名或密码为空");
        }
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(user.getAccount(), user.getPassword());
        Authentication authenticate = authenticationManager.authenticate(authenticationToken);
        Login loginUser = (Login) authenticate.getPrincipal();
        if (Objects.isNull(loginUser)) {
            return Result.fail("用户名或密码错误");
        }
        User user1 = loginUser.getUser();
        Map<String, Object> map = new HashMap<>();
        map.put("userid", user1.getUserId());


        stringRedisTemplate.opsForValue().set("login:" + user1.getUserId().toString(), JSON.toJSONString(loginUser));
        String token = JWTUtil.createToken(map, "helloWorld".getBytes());
        UserDTO userDTO = new UserDTO();
        userDTO.setUserId(user1.getUserId());
        userDTO.setAccount(user1.getAccount());
        userDTO.setJob(user1.getJob());
        userDTO.setName(user1.getName());
        List<Object> list = new ArrayList<>(Arrays.asList(userDTO, token));
        return Result.ok(list);
    }


    public Result userList(User user) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        ReflectUtil<User> checkNullUtil = new ReflectUtil<>();
        checkNullUtil.swaggerCheck(user, wrapper, User.class);
        wrapper.last(" order by job asc , user_id asc");
        List<User> list = userMapper.selectList(wrapper);
        List<UserVo> resList = getResVo(list);
        long size = resList.size();
        return Result.ok(resList, size);
    }

    @Override
    public Result noStudentList(UserVo userVo) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        ReflectUtil<User> checkNullUtil = new ReflectUtil<>();
        checkNullUtil.swaggerCheck(userVo, wrapper, User.class);
        wrapper.ne("job", 3);
        long total = userMapper.selectList(wrapper).size();
        if (userVo.getPage() != null) {
            int start = (userVo.getPage() - 1) * 10;
            wrapper.last("limit " + start + ",10");
        }
        List<User> list = userMapper.selectList(wrapper);

        List<UserVo> resList = getResVo(list);
        return Result.ok(resList, total);

    }

    @Override
    public Result legitimacy(User user) {
        if (user.getName().length() > 10) {
            return Result.fail("名字长度过长");
        }
        if (user.getJob() < 0 || user.getJob() > 3) {
            return Result.fail("user job选择了0~3之外的身份");
        }
        return Result.ok();
    }

    @Override
    public List<UserVo> getResVo(List<User> list) {
        List<UserVo> resList = new ArrayList<>();
        for (User user : list) {
            UserVo userVo = new UserVo();
            BeanUtils.copyProperties(user, userVo);
            userVo.setJobString(StateChangeUtil.userJobChange(user.getJob()));
            resList.add(userVo);
        }
        return resList;
    }

    @Override
    public boolean saveOne(User user) {
        userMapper.saveOne(user);
        return true;
    }

    @Override
    public Result saveUser(User user) {
        String account = getAccount();
        String password = "123456";
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        password = passwordEncoder.encode(password);
        user.setAccount(account);
        user.setPassword(password);
        boolean save = save(user);
        if (!save) {
            return Result.fail("新增用户失败");
        }
        return Result.ok("新增用户成功");
    }

    private String getAccount() {
        //account：年份后两位+月份+四位人数
        LocalDate now = LocalDate.now();
        String account = (Integer.toString(now.getYear()).substring(2));
        String month = Integer.toString(now.getMonthValue());
        month = RedisUtil.pedWithZero(month, "2");
        account += month;
        Integer count = (Integer) redisTemplate.opsForValue().get(Constant.USER_ACCOUNT_PREFIX+account);

        if (count == null) {
            redisTemplate.opsForValue().set(Constant.USER_ACCOUNT_PREFIX+account, 1);
            count = 1;
        }
        redisTemplate.opsForValue().increment(Constant.USER_ACCOUNT_PREFIX+account);

        account += RedisUtil.pedWithZero(String.valueOf(count), "4");
        return account;
    }

}

